package square;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;

/**
 * @author shisan
 * @date 2024/12/12
 * @describe 俄罗斯方块游戏主类
 */
public class Tetris extends JPanel {

    //正在下落的四格方块     调用随机生产一个四方格的方法
    private ParentSquare currentOne = ParentSquare.randomOne();
    //将要下落的四格方块
    private ParentSquare nextOne = ParentSquare.randomOne();
    //墙,20行 10列的 表格  宽度为26
    private Cell[][] wall = new Cell[20][10];

    private static final int CELL_SIZE = 26;

    //游戏分数池
    int[] scores_pool = {0, 1, 2, 5, 10};
    //当前游戏的分数
    private int totalScore = 0;
    //当前消除的行数
    private int totalLine = 0;

    //游戏三种状态 游戏中、暂停、结束
    public static final int PLING = 0;
    public static final int STOP = 1;
    public static final int OVER = 2;
    //当前游戏状态值
    private int game_state=4;
    //显示游戏状态
    String[] show_state = {"P[pause]", "C[continue]", "S[replay]"};
    //游戏三种困难等级 简单、一般、困难
    public static final int EASY = 0;
    public static final int NORMAL = 1;
    public static final int DIFFICU = 2;
    //当前游戏难度等级
    private int game_difficulty;
    //显示游戏难度等级
    String[] show_difficulty = {"1[简单]", "2[一般]", "3[困难]"};
    //插入小方块图片
    public static BufferedImage T;
    public static BufferedImage I;
    public static BufferedImage O;
    public static BufferedImage J;
    public static BufferedImage L;
    public static BufferedImage S;
    public static BufferedImage Z;
    // //插入游戏背景图片
    public static BufferedImage background;

    static {
        try {
            T = ImageIO.read(Tetris.class.getResource("/images/T.png"));
            I = ImageIO.read(Tetris.class.getResource("/images/I.png"));
            O = ImageIO.read(Tetris.class.getResource("/images/O.png"));
            J = ImageIO.read(Tetris.class.getResource("/images/J.png"));
            L = ImageIO.read(Tetris.class.getResource("/images/L.png"));
            S = ImageIO.read(Tetris.class.getResource("/images/S.png"));
            Z = ImageIO.read(Tetris.class.getResource("/images/Z.png"));
            background = ImageIO.read(Tetris.class.getResource("/images/back.png"));

            // gameover = ImageIO.read(Tetris.class.getResource("game-over.png"));


        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //    private boolean gameStarted = false;
    @Override
    public void paint(Graphics g) {
//        super.paintComponent(g);
//        gameStarted = true;
        g.drawImage(background, 0, 0, null);
        //平移坐标轴
        g.translate(15, 15);
        //绘制游戏主区域
        paintWall(g);
        //绘制正在下落的四方格
        paintCurrentOne(g);
        //绘制下一个将要下落的四方格
        paintNextOne(g);
        //绘制游戏得分
        paintScores(g);
        //绘制当前游戏状态
        paintState(g);
//        if (!gameStarted){
//            return;
//        }setDoubleBuffered(true);
    }

    public void reset() {
        if (timer != null) {
            timer.stop(); // 停止计时器
        } 
        // 重置分数
        totalScore = 0;

        wall = new Cell[20][10];
        // 重置其他游戏状态
        game_state = PLING;
        currentOne = ParentSquare.randomOne();
        nextOne = ParentSquare.randomOne();

        // currentPiece = null;
        timer = new Timer(1000, e -> {
            // 定义方块下落的逻辑
            sortDropActive(); // 向下移动当前方块
            repaint(); // 刷新游戏界面
        });
    
        // 重新启动计时器
        timer.setDelay(1000);
        timer.start(); // 根据您的需求设置初始延迟 
        repaint();
    }
    
    
    private Timer timer;
    public void start() {
        timer = new Timer(0,new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                if (game_state == PLING) {
                    adjustTimeDelay();
                    if(camDrop()){
                        currentOne.moveDrop(); //方块下落
                    }else {
                        landToWall(); //方块嵌入到墙中
                        destroyLine();//检查是否消行
                        if (isGameOver()) {
                            game_state = OVER;
                            timer.stop();//游戏结束  停止计时器
                        }else {
                            currentOne = nextOne;
                            nextOne = ParentSquare.randomOne();
                        }
                    }
                    repaint();//重新绘制定时器
                } else if (game_state == OVER){
                    timer.stop();
                }
            }
        });
        timer.start();
        game_state = PLING;
        KeyListener l = new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int code = e.getKeyCode();
                switch (code) {
                    case KeyEvent.VK_DOWN: //下落一格
                        sortDropActive();
                        break;
                    case KeyEvent.VK_LEFT:    //左移
                        moveleftActive();
                        break;
                    case KeyEvent.VK_RIGHT:  //右移
                        moveRightActive();
                        break;
                    case KeyEvent.VK_UP:   //顺时针旋转
                        rotateRightActive();
                        break;
                    case KeyEvent.VK_SPACE:  //瞬间下落
                        hadnDropActive();
                        break;
                    case KeyEvent.VK_P:
                        if (game_state == PLING) {
                            game_state = STOP;
                        }
                        break;
                    case KeyEvent.VK_C:
                        if (game_state == STOP) {
                            game_state = PLING;
                        }
                        break;
                    case KeyEvent.VK_S:
                    if (game_state == OVER) {
                        reset();
                    }
                        
                }
            }
        };
        //将窗口设置为焦点
        this.addKeyListener(l);
        this.requestFocus();
    }
    private void adjustTimeDelay() {
        if (game_difficulty == EASY) {
            timer.setDelay(1000);
        } else if (game_difficulty == NORMAL) {
            timer.setDelay(500);
        } else if (game_difficulty == DIFFICU) {
            timer.setDelay(200);
        }
    }
    //创建顺时针旋转
    public void rotateRightActive() {
        //判断是否越界或者是否重合
        currentOne.rotateRight();
        if (outOFBounds() || coincide()) {
            //如果为真，逆时针旋转回去，相当于没有旋转
            currentOne.rotateLeft();
        }
    }

    //瞬间下落
    public void hadnDropActive() {
        while (true) {
            //判断能否下落
            if (camDrop()) {
                currentOne.moveDrop();
            } else {
                break;
            }
        }
        //将四方格嵌入到墙中
        landToWall();
        //判断是否消行
        destroyLine();
        //判断游戏是否结束
        if (isGameOver()) {
            game_state = OVER;
        } else {
            //当前游戏没有结束时，则产生新的四方格
            currentOne = nextOne;
            nextOne = ParentSquare.randomOne();
        }
    }

    //按键一次，下落一格
    public void sortDropActive() {
        //判断是否下落
        if (camDrop()) {
            //当前四方格下落一格
            currentOne.moveDrop();
        } else {
            //将四方格嵌入到墙中
            landToWall();
            //判断是否消行
            destroyLine();
            //判断游戏是否结束
            if (isGameOver()) {
                game_state = OVER;
            } else {
                //当前游戏没有结束时，则产生新的四方格
                currentOne = nextOne;
                nextOne = ParentSquare.randomOne();
            }
        }
    }

    //单元格嵌入墙中
    private void landToWall() {
        Cell[] cells = currentOne.cells;
        for (Cell cell : cells) {
            int row = cell.getRow();
            int col = cell.getCol();
            wall[row][col] = cell;
        }
    }

    //判断四方格能否下落
    public boolean camDrop() {
        Cell[] cells = currentOne.cells;
        for (Cell cell : cells) {
            int row = cell.getRow();
            int col = cell.getCol();
            //判断是否到达底部
            if (row == wall.length - 1) {
                //如果是最底部则无法下落
                return false;
                //判断当前行的下一行是否有四方格
            } else if (wall[row + 1][col] != null) {
                //如果为真，则无法下落
                return false;
            }
        }
        //说明符合下落的条件
        return true;
    }

    //消除行
    public void destroyLine() {
        //声明变量,统计当前消除的总行数
        int line = 0;
        Cell[] cells = currentOne.cells;
        for (Cell cell : cells) {
            int row = cell.getRow();
            //判断当前行是否已满
            if (isFullLine(row)) {
                line++;
                for (int i = row; i > 0; i--) {
                    System.arraycopy(wall[i - 1], 0, wall[i], 0, wall[0].length);
                }
                wall[0] = new Cell[9];
            }
        }
        //每次消除行在分数池中获取的分数 , 添加到总分数上
        totalScore += scores_pool[line];
        //消除的总行数
        totalLine += line;
    }

    //判断当前行是否已经满了
    public boolean isFullLine(int row) {
        Cell[] cells = wall[row];
        for (Cell cell : cells) {
            if (cell == null) {
                return false;
            }
        }
        return true;
    }

    //判断游戏是否结束
    public boolean isGameOver() {
        Cell[] cells = nextOne.cells;
        for (Cell cell : cells) {
            int row = cell.getRow();
            int col = cell.getCol();
            if (wall[row][col] != null) {
                return true;
            }
        }
        return false;
    }
    //游戏状态具体设置
    private void paintState(Graphics g) {
        if(game_state==PLING){
            g.drawString("正在游戏中",300,275);
        }else if (game_state==STOP){
            g.drawString("游戏暂停",300,275);
            g.setColor(Color.red);
            g.setFont(new Font(Font.SANS_SERIF,Font.BOLD,25));
            g.drawString("游戏已暂停",60,275);
            g.drawString("按C继续游戏",45,320);
        }else if (game_state==OVER){
            g.drawString("游戏结束",300,275);
            g.setColor(Color.red);
            g.setFont(new Font(Font.SANS_SERIF,Font.BOLD,25));
            g.drawString("游戏失败",60,275);
            g.drawString("按S重新游戏",45,320);
        }
        
    }
    //游戏得分/消除行数栏具体设置
    private void paintScores(Graphics g) {
        //设置字体格式，是否加粗，字体大小
        g.setFont(new Font(Font.MONOSPACED, Font.BOLD, 30));
        //使用画笔绘制当前的的得分   X轴控制左右，y轴控制上下
        g.drawString("当前得分:"+totalScore,300,160);
        //使用画笔绘制当前消除的行数
        g.drawString("已消行数:"+totalLine,300,220);

    }
    //下一个小方格具体设置
    private void paintNextOne(Graphics g) {
        //获取nextOne对象的四个元素
        Cell[] cells = nextOne.cells;
        for(Cell s: cells) {
//           获取每一个元素的行号和列号
//            int row = s.getRow();
//            int col = s.getCol();
//            //横坐标
//            int x = col*CELL_SIZE+260;
//            //纵坐标
//            int y = row*CELL_SIZE+26;
            //列*宽度+偏移值
            int x =s.getCol()*CELL_SIZE+260;
            //行*宽度+偏移值
            int y =s.getRow()*CELL_SIZE+26;
            //已知 四方格图片，x,y的定位 通过画笔实现
            g.drawImage(s.getImage(),x,y,null);
        }
    }

    private void paintCurrentOne(Graphics g) {
        //获取当前下落的四方块
        Cell[] cells = currentOne.cells;
        for (Cell cell : cells) {
            int x = cell.getCol() * CELL_SIZE;
            int y = cell.getRow() * CELL_SIZE;
            g.drawImage(cell.getImage(), x, y, null);
        }
    }

    private void paintWall(Graphics g) {
        //外层循环控制行数
        for (int i = 0; i < wall.length; i++) {
            //内层循环控制列数
            for (int j = 0; j < wall[i].length; j++) {
                int x = j * CELL_SIZE;
                int y = i * CELL_SIZE;
                Cell cell = wall[i][j];
                //判断是否有小方块
                if (cell == null) {
                    g.drawRect(x, y, CELL_SIZE, CELL_SIZE);
                } else {
                    g.drawImage(cell.getImage(), x, y, null);
                }
            }
        }
    }

    //判断是否出界
    public boolean outOFBounds() {
        Cell[] cells = currentOne.cells;
        for (Cell cell : cells) {
            int col = cell.getCol();
            int row = cell.getRow();
            if (row < 0 || row > wall.length - 1 || col < 0 || col > wall[0].length-1) {
                return true;
            }
        }
        return false;
    }

    //按键一次，左移一次
    public void moveleftActive() {
        currentOne.moveleft();
        //判断是否越界或重合
        if (outOFBounds() || coincide()) {
            //如果是则整体右移一个格
            currentOne.moveRight();
        }
    }

    //按键一次，右移一次
    public void moveRightActive() {
        currentOne.moveRight();
        //判断是否越界或重合
        if (outOFBounds() || coincide()) {
            //如果是则整体左移一个格
            currentOne.moveleft();
        }
    }

    //判断是否重合
    public boolean coincide() {
        Cell[] cells = currentOne.cells;
        for (Cell cell : cells) {
            int row = cell.getRow();
            int col = cell.getCol();
            if (wall[row][col] != null) {
                return true;
            }
        }
        return false;
    }
    
}

